package hasthi.tools.analyze;

import hasthi.common.HasthiException;
import hasthi.common.LogFile;
import hasthi.common.constants.HasthiConstants;

import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;

/**
 * Each client has his own Data Collector, so it need not be thread safe.
 * If the window size is set, once that when that number of readings are collected, the
 * class publish/write them to a file
 */
public class DataCollector {
    public static int WINDOW_SIZE = 10;
    
    
    private DescriptiveStatistics data = DescriptiveStatistics.newInstance();
    private long start;
    private long end;
    private int failuireCount;
    private boolean nano = true;
    private long readingCount = 0;
    private int windowSize = -1;
    private boolean write2File = true;
    private DataSetBag bag = null;
    private LogFile out = null;
    private String name;
    
    public DataCollector(String name){
        this.name = name;
        String write2fileStr = System.getProperty(HasthiConstants.PERF_WRITE2FILE);
        if(write2fileStr != null && "false".equals(write2fileStr)){
            write2File = false;
        }
    }
    
    public DataCollector(String name,LogFile file, int windowSize){
        this(name);
        this.out = file;
        this.windowSize = windowSize;
    }
    
    public DataCollector(String name,LogFile file){
        this(name);
        this.out = file;
    }

    
    public void setOutputFile(LogFile  logfile){
         out = logfile;
    }
    
    public void reset(){
        data.clear();
        readingCount = 0;
        failuireCount = 0;
    }
    
    public void dumpAndReset() {
        DataSetBag.DataSet dataSet = new DataSetBag.DataSet(this);
        String outstr = "["+ name +"]"+readingCount +"/"+ windowSize + " "+ dataSet.toString();
        //System.out.println(outstr);
        reset();
        try {
            if(bag != null){
                bag.addData(dataSet);
            }
            
            if(write2File){
                if(out == null){
                    out = LogFile.getLog(name);
                }
                out.append(outstr);
            }
        } catch (HasthiException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    public   void startClock(){
        if(nano){
            start = System.nanoTime();
        }else{
            start = System.currentTimeMillis();    
        }
    }
    
    public void actionfailed(){
        failuireCount++;
    }
    
    
    public synchronized void addAReading(double d){
        if(nano){
            data.addValue(d/1000000);    
        }else{
            data.addValue(d);
        }
        
//        if(nano){
//            data.addValue(Math.round(d/1000000));    
//        }else{
//            data.addValue(d);
//        }
        readingCount++;
        if(windowSize != -1 && (readingCount + failuireCount) >= windowSize){
            dumpAndReset();
        }
    }
    
    
    public void endClock(){
        if(nano){
            end = System.nanoTime();
        }else{
            end = System.currentTimeMillis();    
        }
        addAReading(end - start);
    }
    
    public DescriptiveStatistics getData(){
        return data;
    }
    
    public void notifyFaluire(){
        failuireCount++;
    }

    public int getFaluireCount() {
        return failuireCount;
    }

    public void setNano(boolean nano) {
        this.nano = nano;
    }

    public long getReadingCount() {
        return readingCount;
    }

//    public void setWindowSize(int windowSize) {
//        this.windowSize = windowSize;
//    }

    public void setWrite2File(boolean write2File) {
        this.write2File = write2File;
    }

    public void setBag(DataSetBag bag) {
        this.bag = bag;
    }
    
    
    
    
//    public void sendData() throws HasthiException{
//        try {
//            long min = Long.MAX_VALUE;
//            long max = 0;
//            long tot = 0;
//            System.out.println("Faluires "+ faluireCount + "/" + data.size());
//            for(long l:data){
//                if(l < min){
//                    min = l;
//                }
//                if(l > max){
//                    max = l;
//                }
//                tot = tot + l;
//            }
//            System.out.println("Avg =" + tot/data.size() + " Min =" + min + " Max =" + max);
//            
//            PerfDataDocument perfDataDocument = PerfDataDocument.Factory.newInstance();
//            PerfData perfData = perfDataDocument.addNewPerfData();
//            perfData.setName(InetAddress.getLocalHost().getHostName());
//            perfData.setAvg(tot/data.size());
//            perfData.setFaliureCount(faluireCount);
//            perfData.setMax(max);
//            perfData.setMin(min);
//            perfData.setRequestCount(data.size());
//            PerfAgent.getInstance().sendEvent(perfDataDocument);
//        } catch (UnknownHostException e) {
//            throw new HasthiException(e,FaultCode.LocalError);
//        }
//    }
}
